﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Reflection;
using System.Windows.Interop;
using BrainTechLLC.Silverlight.Controls;

namespace BrainTechLLC.Silverlight.ClientApplication
{
    public partial class App : Application
    {
        public static Page _rootPage;
        public static Dispatcher MainDispatcher;
        //public static double SavedWidth;
        //public static double SavedHeight;

        public App()
        {
            this.Startup += this.Application_Startup;
            this.Exit += this.Application_Exit;
            this.UnhandledException += this.Application_UnhandledException;
            this.Host.Content.Resized += new EventHandler(DisplaySizeInformation);

            Notification.RegisterMessageSerializationTypes();

            InitializeComponent();

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditAbility(),
                VisualizerControlType = typeof(EditAbility),
                VisualizerName = "EditAbility",
                VisualizeType = typeof(Ability)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditNameInfo(),
                VisualizerControlType = typeof(EditNameInfo),
                VisualizerName = "EditNameInfo",
                VisualizeType = typeof(NameAndDescription)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditMedia(),
                VisualizerControlType = typeof(EditMedia),
                VisualizerName = "EditMedia",
                VisualizeType = typeof(Media)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditReset(),
                VisualizerControlType = typeof(EditReset),
                VisualizerName = "EditReset",
                VisualizeType = typeof(Reset)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = true,
                CreateVisualizer = () => new GameThingList(),
                VisualizerControlType = typeof(GameThingList),
                VisualizerName = "GameThingList",
                VisualizeType = typeof(object)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = true,
                CreateVisualizer = () => new GameThingTree(),
                VisualizerControlType = typeof(GameThingTree),
                VisualizerName = "GameThingTree",
                VisualizeType = typeof(object)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditState(),
                VisualizerControlType = typeof(EditState),
                VisualizerName = "EditState",
                VisualizeType = typeof(State)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditGameThing(),
                VisualizerControlType = typeof(EditGameThing),
                VisualizerName = "EditGameThing",
                VisualizeType = typeof(object)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditArea(),
                VisualizerControlType = typeof(EditArea),
                VisualizerName = "EditArea",
                VisualizeType = typeof(Area)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditLocationEdge(),
                VisualizerControlType = typeof(EditLocationEdge),
                VisualizerName = "EditLocationEdge",
                VisualizeType = typeof(LocationEdge)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditLocationEdgeData(),
                VisualizerControlType = typeof(EditLocationEdgeData),
                VisualizerName = "EditLocationEdgeData",
                VisualizeType = typeof(LocationEdgeData)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditGameCharTemplate(),
                VisualizerControlType = typeof(EditGameCharTemplate),
                VisualizerName = "EditGameCharTemplate",
                VisualizeType = typeof(GameCharTemplate)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditItemTemplate(),
                VisualizerControlType = typeof(EditItemTemplate),
                VisualizerName = "EditItemTemplate",
                VisualizeType = typeof(ItemTemplate)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditItem(),
                VisualizerControlType = typeof(EditItem),
                VisualizerName = "EditItem",
                VisualizeType = typeof(Item)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditStateTemplate(),
                VisualizerControlType = typeof(EditStateTemplate),
                VisualizerName = "EditStateTemplate",
                VisualizeType = typeof(StateTemplate)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditBasicTemplate(),
                VisualizerControlType = typeof(EditBasicTemplate),
                VisualizerName = "EditBasicTemplate",
                VisualizeType = typeof(Template)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditCommandToPerform(),
                VisualizerControlType = typeof(EditCommandToPerform),
                VisualizerName = "EditCommandToPerform",
                VisualizeType = typeof(CommandToPerform)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = true,
                CreateVisualizer = () => new ShowStatesControl(),
                VisualizerControlType = typeof(ShowStatesControl),
                VisualizerName = "ShowStatesControl",
                VisualizeType = typeof(State)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = true,
                CreateVisualizer = () => new ShowPropertiesControl(),
                VisualizerControlType = typeof(ShowPropertiesControl),
                VisualizerName = "ShowPropertiesControl",
                VisualizeType = typeof(IdentifierAndValue)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = true,
                CreateVisualizer = () => new ShowAbilitiesControl(),
                VisualizerControlType = typeof(ShowAbilitiesControl),
                VisualizerName = "ShowAbilitiesControl",
                VisualizeType = typeof(Ability)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = true,
                CreateVisualizer = () => new ShowLocationEdges(),
                VisualizerControlType = typeof(ShowLocationEdges),
                VisualizerName = "ShowLocationEdges",
                VisualizeType = typeof(LocationEdge)
            });

            //DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            //{
            //    CollectionVisualizer = false,
            //    CreateVisualizer = () => new GameLocationVis1(),
            //    VisualizerControlType = typeof(GameLocationVis1),
            //    VisualizerName = "GameLocationVis1",
            //    VisualizeType = typeof(GameLocation)
            //});

            //DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            //{
            //    CollectionVisualizer = false,
            //    CreateVisualizer = () => new FlexibleTypeEditor(),
            //    VisualizerControlType = typeof(FlexibleTypeEditor),
            //    VisualizerName = "FlexibleTypeEditor",
            //    VisualizeType = typeof(object)
            //});

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = true,
                CreateVisualizer = () => new ShowLocationsControl(),
                VisualizerControlType = typeof(ShowLocationsControl),
                VisualizerName = "ShowLocationsControl",
                VisualizeType = typeof(GameLocation)
            });

            DataVisualizerRegistry.Instance.RegisterVisualizer(new DataVisualizerInfo()
            {
                CollectionVisualizer = false,
                CreateVisualizer = () => new EditGameLocation(),
                VisualizerControlType = typeof(EditGameLocation),
                VisualizerName = "EditGameLocation",
                VisualizeType = typeof(GameLocation)
            });

            CommonInit();
        }

        public void CommonInit()
        {
            string assemblyName;
            Type[] types = Core_RegisterTypes.RegisterTypes();
            TypeProvider.AddTypesForSerialize(types);
            types = TypeProvider_RegisterTypes.RegisterTypes();
            TypeProvider.AddTypesForSerialize(types);
            types = ThreadSafeObjects_RegisterTypes.RegisterTypes(out assemblyName);
            DLLContents contents = TypeProvider.GetInstance().GetDLLContents(assemblyName);
            types.ForEach(type =>
            {
                if (type.IsTypeOkay())
                    TypeProvider.GetInstance().AddType(contents, type);
            });
            TypeProvider.AddTypesForSerialize(types);
            types = PerceptionAndView_RegisterTypes.RegisterTypes();
            TypeProvider.AddTypesForSerialize(types);
            types = Notification_RegisterTypes.RegisterTypes();
            TypeProvider.AddTypesForSerialize(types);
            types = BasicObjects_RegisterTypes.RegisterTypes();
            TypeProvider.AddTypesForSerialize(types);
            AltSerializeHelper.CheckInit(TypeProvider._typesForSerialize.AllItems);
        }

        private void Application_Startup(object sender, StartupEventArgs e)
        {
            DataAccess.CurrentlyPlayingChanged += new EventHandler(DataAccess_CurrentlyPlayingChanged);
            DataAccess.NotificationTextReceived += new EventHandler<ObjectEventArgs<string>>(DataAccess_NotificationTextReceived);
            DataAccess.UpdatePropertyValue += new EventHandler<ObjectEventArgs<string, object>>(DataAccess_UpdatePropertyValue);
            DataAccess.WantEnableHUD += new EventHandler(DataAccess_WantEnableHUD);
            DataAccess.SocketErrorOccurred += new EventHandler<ObjectEventArgs<System.Net.Sockets.SocketAsyncEventArgs>>(DataAccess_SocketErrorOccurred);
            DataAccess.ConnectionErrorOccurred += new EventHandler<ObjectEventArgs<System.Net.Sockets.SocketAsyncEventArgs>>(DataAccess_ConnectionErrorOccurred);
            DataAccess.LocalWorldRead += new EventHandler(DataAccess_LocalWorldRead);
            _rootPage = new Page();
            this.RootVisual = _rootPage;
            MainDispatcher = _rootPage.Dispatcher;

            //SilverlightHost host = Application.Current.Host;
            //Content content = host.Content;
            //content.IsFullScreen = true;

            //Module[] mods = Assembly.GetExecutingAssembly().GetModules();
            //foreach (var mod in mods)
            //{
            //    Console.WriteLine(mod.Assembly.FullName);
            //}
            //mods = Assembly.GetCallingAssembly().GetModules();
            //foreach (var mod in mods)
            //{
            //    Console.WriteLine(mod.Assembly.FullName);
            //}
        }

        void DataAccess_LocalWorldRead(object sender, EventArgs e)
        {
            // HEREHERE
            //_rootPage.showLocations.DataToVisualize = DataAccess.LocalWorld.AllTerminatingItems.Values.ToObservable();
            //_rootPage.showLocations.Visibility = Visibility.Visible;
        }

        void DataAccess_ConnectionErrorOccurred(object sender, ObjectEventArgs<System.Net.Sockets.SocketAsyncEventArgs> e)
        {
            MainDispatcher.BeginInvoke(() => MessageBox.Show("Connection Error"));
        }

        void DataAccess_SocketErrorOccurred(object sender, ObjectEventArgs<System.Net.Sockets.SocketAsyncEventArgs> e)
        {
            MainDispatcher.BeginInvoke(() => MessageBox.Show("Error"));
        }

        void DataAccess_WantEnableHUD(object sender, EventArgs e)
        {
            _rootPage.mainHUD.Enabled = true;
            DataAccess.ThingMoved += new EventHandler<ObjectEventArgsNonRef<long, LocationInt, long>>(DataAccess_ThingMoved);
        }

        void DataAccess_ThingMoved(object sender, ObjectEventArgsNonRef<long, LocationInt, long> e)
        {
            _rootPage.mainHUD.UpdateLocation(e.obj1, e.obj2, e.obj3);
        }

        void DataAccess_UpdatePropertyValue(object sender, ObjectEventArgs<string, object> e)
        {
            MainDispatcher.BeginInvoke(() =>
            {
                if (DataAccess.PropertiesInstance != null)
                {
                    DataAccess.ChangePropertyValueLocally(e.obj1, (int)e.obj2);
                }
            });
        }

        void DataAccess_NotificationTextReceived(object sender, ObjectEventArgs<string> e)
        {
            AppendNotificationText(e.obj);
        }

        void DataAccess_CurrentlyPlayingChanged(object sender, EventArgs e)
        {
            DataAccess.PropertiesInstance = DataAccess.CurrentlyPlaying._properties.Props.AllItems.ToObservable();
            _rootPage.mainHUD.properties.DataToVisualize = DataAccess.PropertiesInstance;// BindToPropertyData(DataAccess.CurrentlyPlaying._properties);
        }

        private void Application_Exit(object sender, EventArgs e)
        {

        }
        private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            // If the app is running outside of the debugger then report the exception using
            // the browser's exception mechanism. On IE this will display it a yellow alert 
            // icon in the status bar and Firefox will display a script error.
            if (!System.Diagnostics.Debugger.IsAttached)
            {

                // NOTE: This will allow the application to continue running after an exception has been thrown
                // but not handled. 
                // For production applications this error handling should be replaced with something that will 
                // report the error to the website and stop the application.
                e.Handled = true;
                Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
            }
        }
        private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
        {
            try
            {
                string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
                errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");

                System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight 2 Application " + errorMsg + "\");");
            }
            catch (Exception)
            {
            }
        }
        private void DisplaySizeInformation(Object sender, EventArgs e)
        {
            _rootPage.Width = this.Host.Content.ActualWidth;
            _rootPage.Height = this.Host.Content.ActualHeight;
            _rootPage.LayoutRoot.Height = this.Host.Content.ActualHeight;
            _rootPage.LayoutRoot.Width = this.Host.Content.ActualWidth;
            _rootPage.UpdateLayout();
            _rootPage.mainHUD.notificationsControl.Width = this.Host.Content.ActualWidth;

            DataVisualizerRegistry.Instance.OnHeightChanged(_rootPage.Height);

            //SavedHeight = this.Host.Content.ActualHeight;
            //SavedWidth = this.Host.Content.ActualWidth - _rootPage.scrollViewer.Width;
            //_rootPage.imgMain.Height = SavedHeight;
            //_rootPage.imgMain.Width = SavedWidth;

            //_rootPage.imgMain.Source = null;
            //_rootPage.LayoutRoot.Children.Clear();
            //_rootPage.LayoutRoot.Children.Add(
            //    new TextBlock { Text = message });
        }


        internal static void AppendNotificationText(string s)
        {
            _rootPage.mainHUD.AppendNotificationText(s);
        }
    }
}
